﻿using SharpHook.Native;
using SyncClipboard.Core.Models.Keyboard;

namespace SyncClipboard.Core.Utilities.Keyboard;

public static class KeyCodeMap
{
    public static readonly Dictionary<KeyCode, Key> Map = new()
    {
        [KeyCode.VcEscape] = Key.Esc,
        [KeyCode.VcF1] = Key.F1,
        [KeyCode.VcF2] = Key.F2,
        [KeyCode.VcF3] = Key.F3,
        [KeyCode.VcF4] = Key.F4,
        [KeyCode.VcF5] = Key.F5,
        [KeyCode.VcF6] = Key.F6,
        [KeyCode.VcF7] = Key.F7,
        [KeyCode.VcF8] = Key.F8,
        [KeyCode.VcF9] = Key.F9,
        [KeyCode.VcF10] = Key.F10,
        [KeyCode.VcF11] = Key.F11,
        [KeyCode.VcF12] = Key.F12,
        [KeyCode.VcF13] = Key.F13,
        [KeyCode.VcF14] = Key.F14,
        [KeyCode.VcF15] = Key.F15,
        [KeyCode.VcF16] = Key.F16,
        [KeyCode.VcF17] = Key.F17,
        [KeyCode.VcF18] = Key.F18,
        [KeyCode.VcF19] = Key.F19,
        [KeyCode.VcF20] = Key.F20,
        [KeyCode.VcF21] = Key.F21,
        [KeyCode.VcF22] = Key.F22,
        [KeyCode.VcF23] = Key.F23,
        [KeyCode.VcF24] = Key.F24,
        [KeyCode.VcBackQuote] = Key.BackQuote,
        [KeyCode.Vc0] = Key._0,
        [KeyCode.Vc1] = Key._1,
        [KeyCode.Vc2] = Key._2,
        [KeyCode.Vc3] = Key._3,
        [KeyCode.Vc4] = Key._4,
        [KeyCode.Vc5] = Key._5,
        [KeyCode.Vc6] = Key._6,
        [KeyCode.Vc7] = Key._7,
        [KeyCode.Vc8] = Key._8,
        [KeyCode.Vc9] = Key._9,
        [KeyCode.VcMinus] = Key.Minus,
        [KeyCode.VcEquals] = Key.Equal,
        [KeyCode.VcBackspace] = Key.Backspace,
        [KeyCode.VcTab] = Key.Tab,
        [KeyCode.VcCapsLock] = Key.Capital,
        [KeyCode.VcA] = Key.A,
        [KeyCode.VcB] = Key.B,
        [KeyCode.VcC] = Key.C,
        [KeyCode.VcD] = Key.D,
        [KeyCode.VcE] = Key.E,
        [KeyCode.VcF] = Key.F,
        [KeyCode.VcG] = Key.G,
        [KeyCode.VcH] = Key.H,
        [KeyCode.VcI] = Key.I,
        [KeyCode.VcJ] = Key.J,
        [KeyCode.VcK] = Key.K,
        [KeyCode.VcL] = Key.L,
        [KeyCode.VcM] = Key.M,
        [KeyCode.VcN] = Key.N,
        [KeyCode.VcO] = Key.O,
        [KeyCode.VcP] = Key.P,
        [KeyCode.VcQ] = Key.Q,
        [KeyCode.VcR] = Key.R,
        [KeyCode.VcS] = Key.S,
        [KeyCode.VcT] = Key.T,
        [KeyCode.VcU] = Key.U,
        [KeyCode.VcV] = Key.V,
        [KeyCode.VcW] = Key.W,
        [KeyCode.VcX] = Key.X,
        [KeyCode.VcY] = Key.Y,
        [KeyCode.VcZ] = Key.Z,
        [KeyCode.VcOpenBracket] = Key.OpenBracket,
        [KeyCode.VcCloseBracket] = Key.CloshBracket,
        [KeyCode.VcBackslash] = Key.BackSlash,
        [KeyCode.VcSemicolon] = Key.Semicolon,
        [KeyCode.VcQuote] = Key.Quote,
        [KeyCode.VcEnter] = Key.Enter,
        [KeyCode.VcComma] = Key.Comma,
        [KeyCode.VcPeriod] = Key.Period,
        [KeyCode.VcSlash] = Key.Slash,
        [KeyCode.VcSpace] = Key.Space,
        [KeyCode.Vc102] = Key.OEM_102,
        [KeyCode.VcMisc] = Key.OEM_8,
        [KeyCode.VcPrintScreen] = Key.PrintScreen,
        [KeyCode.VcScrollLock] = Key.Scroll,
        [KeyCode.VcPause] = Key.Pause,
        [KeyCode.VcCancel] = Key.Cancel,
        [KeyCode.VcHelp] = Key.Help,
        [KeyCode.VcInsert] = Key.Insert,
        [KeyCode.VcDelete] = Key.Delete,
        [KeyCode.VcHome] = Key.Home,
        [KeyCode.VcEnd] = Key.End,
        [KeyCode.VcPageUp] = Key.PgUp,
        [KeyCode.VcPageDown] = Key.PgDn,
        [KeyCode.VcUp] = Key.Up,
        [KeyCode.VcLeft] = Key.Left,
        [KeyCode.VcRight] = Key.Right,
        [KeyCode.VcDown] = Key.Down,
        [KeyCode.VcNumLock] = Key.NumLock,
        [KeyCode.VcNumPadClear] = Key.Clear,
        [KeyCode.VcNumPadDivide] = Key.Divide,
        [KeyCode.VcNumPadMultiply] = Key.Multiply,
        [KeyCode.VcNumPadSubtract] = Key.Subtract,
        [KeyCode.VcNumPadEquals] = Key.NumPadEqual,
        [KeyCode.VcNumPadAdd] = Key.Add,
        [KeyCode.VcNumPadEnter] = Key.NumPadReturn,
        [KeyCode.VcNumPadDecimal] = Key.Decimal,
        [KeyCode.VcNumPadSeparator] = Key.Separator,
        [KeyCode.VcNumPad0] = Key.NumPad0,
        [KeyCode.VcNumPad1] = Key.NumPad1,
        [KeyCode.VcNumPad2] = Key.NumPad2,
        [KeyCode.VcNumPad3] = Key.NumPad3,
        [KeyCode.VcNumPad4] = Key.NumPad4,
        [KeyCode.VcNumPad5] = Key.NumPad5,
        [KeyCode.VcNumPad6] = Key.NumPad6,
        [KeyCode.VcNumPad7] = Key.NumPad7,
        [KeyCode.VcNumPad8] = Key.NumPad8,
        [KeyCode.VcNumPad9] = Key.NumPad9,
        [KeyCode.VcLeftShift] = Key.Shift,
        [KeyCode.VcRightShift] = Key.Shift,
        [KeyCode.VcLeftControl] = Key.Ctrl,
        [KeyCode.VcRightControl] = Key.Ctrl,
        [KeyCode.VcLeftAlt] = Key.Alt,
        [KeyCode.VcRightAlt] = Key.Alt,
        [KeyCode.VcLeftMeta] = Key.Meta,
        [KeyCode.VcRightMeta] = Key.Meta,
        [KeyCode.VcContextMenu] = Key.Apps,
        [KeyCode.VcFunction] = Key.Function,
        [KeyCode.VcChangeInputSource] = Key.ChangeInputSource,
        [KeyCode.VcPower] = Key.Power,
        [KeyCode.VcSleep] = Key.Sleep,
        [KeyCode.VcMediaPlay] = Key.MediaPlayPause,
        [KeyCode.VcMediaStop] = Key.MediaStop,
        [KeyCode.VcMediaPrevious] = Key.MediaPrevTrack,
        [KeyCode.VcMediaNext] = Key.MediaNextTrack,
        [KeyCode.VcMediaSelect] = Key.LaunchMediaSelect,
        [KeyCode.VcMediaEject] = Key.MediaEject,
        [KeyCode.VcVolumeMute] = Key.VolumeMute,
        [KeyCode.VcVolumeDown] = Key.VolumeDown,
        [KeyCode.VcVolumeUp] = Key.VolumeUp,
        [KeyCode.VcApp1] = Key.LaunchApp1,
        [KeyCode.VcApp2] = Key.LaunchApp2,
        [KeyCode.VcApp3] = Key.LaunchApp3,
        [KeyCode.VcApp4] = Key.LaunchApp4,
        [KeyCode.VcAppBrowser] = Key.LaunchBrowser,
        [KeyCode.VcAppCalculator] = Key.LaunchCalculator,
        [KeyCode.VcAppMail] = Key.LaunchMail,
        [KeyCode.VcBrowserSearch] = Key.BrowserSearch,
        [KeyCode.VcBrowserHome] = Key.BrowserHome,
        [KeyCode.VcBrowserBack] = Key.BrowserBack,
        [KeyCode.VcBrowserForward] = Key.BrowserForward,
        [KeyCode.VcBrowserStop] = Key.BrowserStop,
        [KeyCode.VcBrowserRefresh] = Key.BrowserRefresh,
        [KeyCode.VcBrowserFavorites] = Key.BrowserFavorites,
        [KeyCode.VcKatakanaHiragana] = Key.KatakanaHiragana,
        [KeyCode.VcKatakana] = Key.Katakana,
        [KeyCode.VcHiragana] = Key.Hiragana,
        [KeyCode.VcKana] = Key.Kana,
        [KeyCode.VcKanji] = Key.Kanji,
        [KeyCode.VcHangul] = Key.Hangul,
        [KeyCode.VcJunja] = Key.Junja,
        [KeyCode.VcFinal] = Key.Final,
        [KeyCode.VcHanja] = Key.Hanja,
        [KeyCode.VcAccept] = Key.Accept,
        [KeyCode.VcConvert] = Key.Convert,
        [KeyCode.VcNonConvert] = Key.Nonconvert,
        [KeyCode.VcImeOn] = Key.ImeOn,
        [KeyCode.VcImeOff] = Key.ImeOff,
        [KeyCode.VcModeChange] = Key.Modechange,
        [KeyCode.VcProcess] = Key.PROCESSKEY,
        [KeyCode.VcAlphanumeric] = Key.Alphanumeric,
        [KeyCode.VcUnderscore] = Key.Underscore,
        [KeyCode.VcYen] = Key.Yen,
        [KeyCode.VcJpComma] = Key.JpComma
    };

    public static readonly Dictionary<Key, KeyCode> MapReverse = Reverse(Map);

    private static Dictionary<TV, TK> Reverse<TK, TV>(Dictionary<TK, TV> oldDict) where TV : notnull where TK : notnull
    {
        var newDict = new Dictionary<TV, TK>();
        foreach (var (key, value) in oldDict)
        {
            newDict.TryAdd(value, key);
        }

        return newDict;
    }
}